package zdream.pmfield.stage.buff.ailment;

import java.util.Arrays;

import zdream.pmfield.data.foe.MoveAdditionalEffects;
import zdream.pmfield.data.foe.VStat;
import zdream.pmfield.stage.buff.foe.FoeStageBuff;
import zdream.pmfield.stage.director.AttackContext;
import zdream.pmfield.stage.director.Roll;
import zdream.pmfield.stage.director.HookType;
import zdream.pmfield.stage.director.Hooks;
import zdream.pmfield.stage.message.RollReportMessage;
import zdream.pmfield.stage.message.FoeRemoveBuffMessage;
import zdream.pmfield.stage.object.FoeActor;

/**
 * 每轮行动前, 会进行 {@link zdream.pmfield.data.foe.VStat#LUCK} 判定
 * 使用两个骰子, 精确度 -20, 大失败时直接跳过回合.
 * 出现第 3 次大失败后, 本状态自动消失.
 *
 * <p>瞌睡状态下所受攻击伤害 +25% (防御降为 80%)
 * <p>下雪天或者麻痹状态下, 第一个骰子必定失败; TODO
 * </p>
 *
 * @author Zdream
 * @date 2023-12-03
 * @since 0.0.1
 */
public class DrowsyBuff extends FoeStageBuff {
	public static final String CATEGORY = MoveAdditionalEffects.E_DROWSY;
	public int majorFailCount = 0, majorFailTotal = 3;

	public DrowsyBuff(FoeActor target) {
		super(target);
	}

	@Override
	public void init() {
		preventSameBuffBeforeFoeReceiveBuff();
		onHook(HookType.BEFORE_FOE_TURN_START)
				.handle(this::checkIsAllowedToAct)
				.buildAndSave();
		onHook(HookType.ON_CHECK_TYPE_FIXED)
				.handle(this::increaseDamage)
				.buildAndSave();
	}

	private void checkIsAllowedToAct(Hooks.HookContext rawContext) {
		Hooks.BeforeTurnHookContext context = rawContext.as();
		if (context.foe != this.target) {
			return;
		}

		Roll[] rolls = new Roll[2];
		for (int i = 0; i < rolls.length; i++) {
			rolls[i] = target.createRoll(VStat.LUCK, -20);
		}

		// 瞌睡状态下行动前需要判定, 大失败时不能行动
		Hooks.RollCheckHookContext rollHooks = target.triggerHook(HookType.DURING_ROLL_CHECK).as();
		rollHooks.withRolls(rolls).withFoe(target).withTitle(CATEGORY).run();

		pushMessage(new RollReportMessage(target, rolls).withTitle(CATEGORY));

		long count = Arrays.stream(rolls)
				.filter(roll -> roll.result)
				.count();

		if (count == 0) {
			++majorFailCount;
			// 确定了本轮不能行动
			context.allowAct = false;
			context.allowActRejectBy = this;
		}

		// 第 3 次大失败后, 本状态自动消失
		if (majorFailCount >= majorFailTotal) {
			target.removeBuff(this);
			pushMessage(new FoeRemoveBuffMessage(this));
		}
	}

	private void increaseDamage(Hooks.HookContext rawContext) {
		final Hooks.AttackHookContext context = rawContext.as();
		final AttackContext attackContext = context.attackContext;

		for (AttackContext.AttackContextItem item : attackContext.items) {
			if (item.targetFoe != target) {
				continue;
			}

			item.defenseFixed *= 0.8f;
		}
	}

	@Override
	public String getCategory() {
		return CATEGORY;
	}

	@Override
	public String toString() {
		return "瞌睡";
	}
}
